require "yaml"
require "benchmark"
require "rubygems"

module Interpleter
  if RUBY_PLATFORM == "java"
    require "java"
    include_class "org.jruby.runtime.Constants"
    Info = {
      "name" => "jruby",
      "version" => Constants::VERSION,
      "banner" => `jruby -v`.chomp,
      "runtime" => {
        "name" => "Java",
        "version" => ENV_JAVA["java.version"],
      }
    }
  else
    Info = {
      "name" => "ruby",
      "version" => RUBY_VERSION,
      "banner" => `ruby -v`.chomp,
    }
  end
end

class Runner
  attr_reader :meta, :scriptfile, :targetfile, :n

  def initialize(scriptfile, targetfile, n)
    script, meta = File.read(scriptfile).split(/__END__/, 2)
    include!(script)

    @meta = YAML.load(meta)
    if gem = @meta["library"].delete("gem")
      spec = Gem.source_index.search(gem).sort_by{|e| e.version}.last
      @meta["library"]["name"] = spec.name
      @meta["library"]["version"] = spec.version.to_s
    end

    @scriptfile = scriptfile
    @targetfile = targetfile
    @n = n
  end

  def measure
    result = 0
    t = Benchmark.measure {
      @n.times {
        result += run(@targetfile)
      }
    }
    [t, result]
  end

  def measure_and_output
    t, result = measure
    y = {
      "benchmark_script" => @scriptfile,
      "language" => "ruby",
      "result" => {
        @targetfile => {
          "loaded" => result,
          "wallclock" => t.real,
        }
      }
    }
    y["library"] = meta["library"]
    y["interpreter"] = Interpleter::Info
    puts YAML.dump({meta["name"] => y})
  end

  def include!(script)
    metaclass = class <<self; self; end
    metaclass.class_eval script
  end
  private :include!
end

def run_benchmark_script(scriptfile, targetfile, n)
  runner = Runner.new(scriptfile, targetfile, n)
  runner.measure_and_output
end

script, target, n = ARGV[0], ARGV[1], ARGV[2].to_i
run_benchmark_script(script, target, n)
